#include "magcad.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QPropertyAnimation>

// 临时
#include <BRepBuilderAPI_MakeVertex.hxx>

MagCAD::MagCAD(QWidget *parent)
    : QWidget(parent)
{

    //提供X server的连接，在window和Mac中不起作用
    Handle(Aspect_DisplayConnection) hAspect_DisplayConnect = new Aspect_DisplayConnection;
    //创建3D接口定义图形驱动
    Handle(OpenGl_GraphicDriver) driver = new OpenGl_GraphicDriver(hAspect_DisplayConnect);

    //该类的方法允许编辑、询问连接该类的其他参数（如视图、光）
    viewer = new V3d_Viewer(driver);
    view = viewer->CreateView();

    WId win_handle = winId();
    // qDebug()<< win_handle;
    //在已有的窗口上创建窗口
    window = new WNT_Window((Aspect_Handle)win_handle);
    view->SetWindow(window);
    if (!window->IsMapped())
    {
        window->Map();//打开窗口
    }

    view->SetBackgroundColor(Quantity_NOC_WHITE);
    view->MustBeResized();
    view->Redraw();
    viewer->SetDefaultLights();

    this->setMouseTracking(true);
    this->setAutoFillBackground(false);
    this->setAttribute(Qt::WA_NoSystemBackground);
    this->setAttribute(Qt::WA_PaintOnScreen);
    this->setBackgroundRole(QPalette::NoRole);
    //交互式上下文

    context = new AIS_InteractiveContext(viewer);
    context->SetDisplayMode(AIS_Shaded, Standard_True);


    // TopoDS_Shape boxShape = occ.MakeBottle(50, 70, 30);

    // Quantity_Color color = Quantity_Color(0.3, 0.5, 0.3, Quantity_TOC_RGB);



    // Handle(AIS_Shape) abox = new AIS_Shape(boxShape);

    // context->SetMaterial(abox, Graphic3d_NameOfMaterial_Stone, Standard_False);
    // context->SetColor(abox, color, Standard_False);

    // context->Display(abox, 1,1,Standard_True);
    // view->FitAll();

    QPushButton *button1 = new QPushButton("Fit All", this);
    button1->move(0, 0);
    button1->show();

    m_cameraAnimation = new V3dViewCameraAnimation(view, this);
    Handle_Graphic3d_Camera m_cameraStart = new Graphic3d_Camera;
    Handle_Graphic3d_Camera m_cameraEnd = new Graphic3d_Camera;
    QPropertyAnimation* V3dViewCameraAnimation = new QPropertyAnimation(this);
    connect(button1, &QPushButton::clicked, this, [&](){
        m_cameraAnimation->configure(&V3dView_fitAll);
        m_cameraAnimation->start(QAbstractAnimation::KeepWhenStopped);
    });

}

MagCAD::~MagCAD(){}

void MagCAD::paintEvent(QPaintEvent* event)
{
    view->Redraw();
}

void MagCAD::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);

    // if (view) {
        view->MustBeResized();
        view->Redraw();
    // }
}


QPaintEngine* MagCAD::paintEngine() const
{
    return 0;
}
void MagCAD::mousePressEvent(QMouseEvent* event)
{
    //平移 鼠标右键+shift
    if ((event->buttons() & Qt::RightButton))//&& (QApplication::keyboardModifiers() == Qt::ShiftModifier))
    {
        m_mode = Action3d_Panning;
        m_x = event->pos().x();
        m_y = event->pos().y();
    }
    else if (event->buttons() & Qt::MiddleButton)//旋转
    {
        m_mode = Action3d_Rotation;
        //开始旋转视图围绕屏幕轴
        view->StartRotation(event->pos().x(), event->pos().y());
    }
}
void MagCAD::mouseReleaseEvent(QMouseEvent* event)
{
    m_mode = Action3d_Nothing;
}

void MagCAD::mouseMoveEvent(QMouseEvent* event)
{
    switch (m_mode)
    {
    case MagCAD::Action3d_Panning:
        view->Pan(event->pos().x() - m_x, m_y - event->pos().y());
        m_x = event->pos().x();
        m_y = event->pos().y();
        break;
    case MagCAD::Action3d_Rotation:
        view->Rotation(event->pos().x(), event->pos().y());
        break;
    default:
        break;
    }
}
//缩放
//Zoom方法通过相邻两侧鼠标位置来判断缩小或者放大，以及缩放程度。鼠标滚轮event->angleDelta().y()会返回数值，以此模拟第二次鼠标位置
#include <Aspect_ScrollDelta.hxx>
void MagCAD::wheelEvent(QWheelEvent* event)
{

    // // 根据鼠标滚轮方向进行缩放
    if(event->angleDelta().y() > 0){
        view->SetZoom(1.1);
    } else {
        view->SetZoom(0.9);
    }
}


void MagCAD::addRriangle(QList<QPointF> Points){

    gp_Pnt point1(Points[0].rx(), Points[0].ry(), 0.0);
    gp_Pnt point2(Points[1].rx(), Points[1].ry(), 0.0);
    gp_Pnt point3(Points[2].rx(), Points[2].ry(), 0.0);

    // 创建三角形的边
    TopoDS_Vertex vertex1 = BRepBuilderAPI_MakeVertex(point1);
    TopoDS_Vertex vertex2 = BRepBuilderAPI_MakeVertex(point2);
    TopoDS_Vertex vertex3 = BRepBuilderAPI_MakeVertex(point3);

    TopoDS_Edge edge1 = BRepBuilderAPI_MakeEdge(vertex1, vertex2);
    TopoDS_Edge edge2 = BRepBuilderAPI_MakeEdge(vertex2, vertex3);
    TopoDS_Edge edge3 = BRepBuilderAPI_MakeEdge(vertex3, vertex1);
    TopoDS_Wire wire = BRepBuilderAPI_MakeWire(edge1, edge2, edge3);
    // 创建可视化对象，只用边显示
    // Handle_Prs3d_Drawer edgeDrawer = new Prs3d_LineAspect(Quantity_NOC_YELLOW, Aspect_TOL_SOLID, 1.0);
    Handle_AIS_Shape edgeObject = new AIS_Shape(wire);
    // edgeObject->Attributes()->SetInfiniteState(true);
    // edgeObject->Attributes()->SetDisplayMode(AIS_Shaded, Standard_False);
    // edgeObject->Attributes()->SetFaceBoundaryDraw(Standard_True);
    // edgeObject->Attributes()->SetLineAspect(edgeDrawer);

    // 将三角形的边对象添加到显示上下文中
    // context->Display(edgeObject, Standard_True);
    // 创建组合对象
    // 创建BRep_Builder对象

    builder.Add(compound, edgeObject->Shape());
}

void MagCAD::showMesh(const GMesh& mesh){
    // 清除所有内容
    context->EraseAll(Standard_False);
    builder.MakeCompound(compound);
    std::vector<std::vector<double>> coord = mesh.getcoord();
    std::vector<std::vector<uint>> element_S = mesh.getelement_S();

    for(uint i = 0; i < element_S.size(); i++){
        QList<QPointF> Points;
        for(uint j = 2; j < element_S[0].size(); j++){
            QPointF Point{coord[element_S[i][j]-1][1], coord[element_S[i][j]-1][2]};
            Points.append(Point);
        }
        // 将第一个图形添加到组合对象中
        addRriangle(Points);
    }
    Handle_AIS_Shape compoundAisShape = new AIS_Shape(compound);
    context->Display(compoundAisShape, Standard_True);
    view->FitAll();
}





V3dViewCameraAnimation::V3dViewCameraAnimation(const Handle_V3d_View& view, QObject* parent)
    : QAbstractAnimation(parent),
    m_view(view),
    m_cameraStart(new Graphic3d_Camera),
    m_cameraEnd(new Graphic3d_Camera)
{
}

int V3dViewCameraAnimation::duration() const
{
    return m_duration_ms;
}

void V3dViewCameraAnimation::setDuration(int msecs)
{
    m_duration_ms = msecs;
}

void V3dViewCameraAnimation::setCameraStart(const Handle_Graphic3d_Camera& camera)
{
    m_cameraStart->Copy(camera);
}

void V3dViewCameraAnimation::setCameraEnd(const Handle_Graphic3d_Camera& camera)
{
    m_cameraEnd->Copy(camera);
}

const QEasingCurve& V3dViewCameraAnimation::easingCurve() const
{
    return m_easingCurve;
}

void V3dViewCameraAnimation::setEasingCurve(const QEasingCurve& easingCurve)
{
    m_easingCurve = easingCurve;
}

void V3dViewCameraAnimation::configure(const std::function<void(Handle_V3d_View)>& fnViewChange)
{
    if (this->state() == QAbstractAnimation::Running)
        this->stop();

    const bool wasImmediateUpdateOn = m_view->SetImmediateUpdate(false);
    m_cameraStart->Copy(m_view->Camera());
    fnViewChange(m_view);
    m_cameraEnd->Copy(m_view->Camera());
    m_view->Camera()->Copy(m_cameraStart); // Restore
    m_view->SetImmediateUpdate(wasImmediateUpdateOn);
}

void V3dViewCameraAnimation::updateCurrentTime(int currentTime)
{
    const double t = m_easingCurve.valueForProgress(currentTime / double(m_duration_ms));
    const bool prevImmediateUpdate = m_view->SetImmediateUpdate(false);
    const Graphic3d_CameraLerp cameraLerp(m_cameraStart, m_cameraEnd);
    Handle_Graphic3d_Camera camera = m_view->Camera();
    cameraLerp.Interpolate(t, camera);
    m_view->SetCamera(camera);
    m_view->ZFitAll();
    m_view->SetImmediateUpdate(prevImmediateUpdate);
    m_view->Update();
}


void V3dView_fitAll(const Handle_V3d_View& view)
{
    view->ZFitAll();
    view->FitAll(0.01, false);
}

